/*!
 * Sketch (2013-11-24, 17:28)
 *
 * Copyright (C) 2011-2013 Hakim El Hattab, http://hakim.se
 */
window.sketch = {};

sketch.IO = function () {
    
	function e(e, t) {
        return e || 0 == e ? e : t;
    }
    
    var t = "/php/sketch.php";
    var o = "/php/sketch.php";
    var n = "/php/gallery.php";
    var a = "x";
    var i = null;
    
    return {
        initialize: function () {
            i = sketch.Main.linesToJSON();
        },
        hasUnsavedChanges: function () {
            return sketch.Main.linesToJSON() !== i;
        },
        saveSketch: function () {
            var e = sketch.Main.linesToJSON();
            this.hasUnsavedChanges() ? e.length > 255 ? (sketch.LoadingOverlay.show("Saving sketch", 100), $.post(t, "save=" + e, function (t) {
                sketch.LoadingOverlay.hide(), t.match(/error/gi) ? alert("Uh-oh, the server replied with a no-no :( Wait a minute and try again.") : (i = e, sketch.URL.writeID(t), sketch.Facebook.isConnected() && FB.api("/me/sketchtoy:draw", "post", {
                    sketch: sketch.Main.getSketchShareURL()
                }, function (e) {
                    !e || e.error
                }), sketch.ShareOverlay.show(), sketch.Related.update());
            })) : alert("Please draw more before saving.") : sketch.ShareOverlay.show();
        },
        loadSketch: function (e, t) {
            $.get(o, {
                load: e
            }, function (e, o) {
                if (e.match(/error/gi)){
                	alert("There was an error loading your sketch.");
                	t("error", {});
                } else {
                    i = e;
                    var o = "success";
                    try {
                        var n = sketch.IO.parseSketch($.parseJSON(e));
                    } catch (a) {
                        o = "error";
                        alert("Uh-oh, an error occured while trying to load this sketch.");
                    }
                    t(o, n);
                }
            });
        },
        parseSketch: function (t) {
            
        	for (var o = e(t.p, t.perspective), n = e(t.a, t.amplitude), i = e(t.l, t.lines), r = 0; i.length > r; r++) {
                
            	i[r].color = e(i[r].c, "#000000");
                i[r].thickness = e(i[r].t, i[r].thickness);
                i[r].perspective = e(i[r].p, i[r].perspective);
                i[r].dashed = e(i[r].d, i[r].dashed);
                i[r].eraser = e(i[r].e, i[r].eraser);
                i[r].points = e(e(i[r].l, i[r].points), []);
                
                for (var s = i[r].points, c = 0; s.length > c; c++) {
                    var l = {position: {x: 0,y: 0},normal: {x: 0,y: 0}};
                    "string" == typeof s[c] ? (l.position.x = parseFloat(s[c].slice(0, s[c].indexOf(a))), l.position.y = parseFloat(s[c].slice(s[c].indexOf(a) + 1))) : (l.position.x = s[c].x, l.position.y = s[c].y), l.normal.x = l.position.x, l.normal.y = l.position.y, s[c] = l
                }
            }

            for (var r = 0; i.length > r; r++) {
                var s = i[r].points;
                0 === s.length && (i.splice(r, 1), r--);
            }
            
            return {
                perspective: o,
                amplitude: n,
                lines: i
            };
        },
        loadGalleryItems: function (e, t, o, a) {
            $.get(n, {
                		load: e,
                		start: t,
                		end: o
            		}, 
            		function (e, t) {
            			if (e.match(/error/gi)){
            				alert("There was an error loading the sketches.");
            			} else {
            				var t = "success";
            				var o = 1;
            				var n = [];
                    
            				try {
            					e = $.parseJSON(e), o = e.totalRows;
            					for (var i = 0; e.sketches.length > i; i++) {
            						var r = r.IO.parseSketch(e.sketches[i].value);
            						r.id = e.sketches[i].id;
            						r.date = e.sketches[i].date;
            						r.views = e.sketches[i].views;
            						n.push(r);
            					}
            				} catch (s) {
            					t = "error", alert("Uh-oh, an error occured while trying to load the sketches.");
            				}
                    
            				a(t, n, o);
            			}
            		}
            );
        }
    }
}();

sketch.URL = function () {

	var t = "";
    
    return {
        readID: function () {
            var e = window.location.pathname.split("/")[1];
            return t.length ? t : e.length ? e : window.location.hash.slice(1);
        },
        writeID: function (o) {
            t = o, !(!window.history || !history.pushState) && history.pushState({}, "Sketch Toy: " + o, "/" + o);
            var n = $('meta[property="og:url"]');
            0 === n.length && (n = $('<meta property="og:url" />'), n.appendTo($("head"))), n.attr("content", sketch.Main.getSketchShareURL());
        }
    };
}();

sketch.Util = function () {
    return {
        hexToRGB: function (e) {
            return "string" == typeof e ? (e = e.split("#").join(""), {
                r: parseInt(e.slice(0, 2), 16),
                g: parseInt(e.slice(2, 4), 16),
                b: parseInt(e.slice(4, 6), 16)
            }) : {
                r: 0,
                g: 0,
                b: 0
            };
        },
        wrapNumber: function (e, t) {
            return e > t ? -t + e % t : -t > e ? t + e % t : e;
        },
        distanceBetween: function (e, t) {
            var o = e.x - t.x,
                n = e.y - t.y;
            return Math.sqrt(o * o + n * n);
        },
        supportsLocalStorage: function () {
            try {
            	localStorage.setItem("t", "t");
            	localStorage.removeItem("t");
                return true;
            } catch (e) {
                return false;
            }
        },
        isTouchDevice: function () {
            return !!navigator.userAgent.match(/ipod|ipad|iphone|android/gi);
        }
    };
}(), window.requestAnimFrame = function () {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (e) {
        window.setTimeout(e, 1e3 / 60)
    }
}(),
/*
window.requestAnimFrame = function () {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (e) {
        window.setTimeout(e, 1e3 / 60);
    };
}();
*/
sketch.Locale = function () {
	
    var a = "sketch-toy-language";
    var i = "en";
    var r = {
            en: {
                "new": "New",
                save: "Save",
                undo: "Undo",
                erase: "Erase",
                size: "Size",
                vibration: "Vibration",
                color: "Color",
                show: "Show",
                hide: "Hide",
                remove: "Remove",
                share: "Share",
                send: "Send",
                tweet: "Tweet",
                "share-link": "Link",
                "share-fb": "Share",
                "share-fb-message": "Send Message",
                "share-tweet": "Tweet",
                "share-email": "Email",
                "share-upload": "Upload Image",
                "share-download": "Download Image",
                "featured-sketches": "Featured Sketches",
                comments: "Comments",
                "connect-fb": "Connect With Facebook",
                language: "Language",
                terms: "Terms of Service",
                privacy: "Privacy",
                "promotion-title": "Sketch Toy",
                "promotion-body": "Sketch using animated lines and share replays with friends!",
                "sketch-fb": "An animated sketch! Click to replay.",
                "sketch-tweet": "Check out this drawing!",
                "alert-unsaved-statement": "The current drawing will be lost",
                "alert-unsaved-confirmation": "The current drawing will be lost, do you want to continue?"
            }
        };
    var s = i;
    var c = $(".select-language");
    
    return {
        initialize: function(){
        	
        	if (sketch.Util.supportsLocalStorage()) {
        		
        		s = localStorage.getItem(a);
        		
        		if(SketchConfig.autodetectLanguage && !s){
        			var e = window.navigator.userLanguage || window.navigator.language;
        			alert(e);
                    e && (e = e.slice(0, 2).toLowerCase(), r[e] && (sketch.Main.trackEvent("Locale", "Change Automatically", e, null, true), s = e, sketch.Util.supportsLocalStorage() && localStorage.setItem(a, s)));
        		}
                
            }
        	
            r[s] || (s = i);
            
            var e = $(".toolbar");
            e.find(".new-button").text(sketch.Locale.string("new"));
            e.find(".save-button").text(sketch.Locale.string("save"));
            e.find(".undo-button").text(sketch.Locale.string("undo"));
            e.find(".eraser-toggle").text(sketch.Locale.string("erase"));
            e.find(".facebook-share .label").text(sketch.Locale.string("share"));
            e.find(".facebook-send .label").text(sketch.Locale.string("send"));
            e.find(".tweet-button .label").text(sketch.Locale.string("tweet"));
            e.find(".size-dropdown .dropdown-title .label").text(sketch.Locale.string("size") + ":");
            e.find(".color-dropdown .dropdown-title .label").text(sketch.Locale.string("color"));
            e.find(".color-dropdown .dropdown-title .label").text(sketch.Locale.string("color"));
            e.find(".vibration-dropdown .dropdown-title .label").text(sketch.Locale.string("vibration") + ":");
            
            var t = $(".share-overlay");
            t.find(".url .label").text(sketch.Locale.string("share-link") + ":");
            t.find(".share-facebook .label").text(sketch.Locale.string("share-fb"));
            t.find(".share-facebook-message .label").text(sketch.Locale.string("share-fb-message"));
            t.find(".share-facebook-photo .label").text(sketch.Locale.string("share-upload"));
            t.find(".share-email .label").text(sketch.Locale.string("share-email"));
            t.find(".share-twitter .label").text(sketch.Locale.string("share-tweet"));
            t.find(".share-download .label").text(sketch.Locale.string("share-download"));
            
            var o = $("footer");
            o.find(".links .terms").text(sketch.Locale.string("terms"));
            o.find(".links .privacy").text(sketch.Locale.string("privacy"));
            c.find(".button .label").text(sketch.Locale.string("language") + ":");
            c.find(".button .value").text(c.find(".list li[data-language=" + s + "]").text());
            c.removeClass("loading");
            
            var n = e.get(0);
            var a = e.css("display");
            
            n.style.display = "none", n.offsetHeight, n.style.display = a;
            
            c.find("li").on("click", function (e) {
                var t = $(e.target).attr("data-language");
                "string" == typeof t && r[t] && sketch.Locale.change(t);
            });
            
            c.on("mouseenter", function () {
                c.find(".list").show();
            });
            
            c.on("mouseleave", function () {
                c.find(".list").hide();
            });
        },
        string: function (e) {
            var t = r[s] || t[i],
                o = t[e];
            return o === void 0 && (o = r[i][e]), o === void 0 && (o = ""), o;
        },
        change: function (e) {
            r[e] && (sketch.Main.trackEvent("Locale", "Change", e), s = e, sketch.Util.supportsLocalStorage() && localStorage.setItem(a, s), window.location.reload());
        }
    };
}();

sketch.Related = function () {
    function e() {
        i = $(".related");
        r = $(".related-gallery");
        s = $(".related-comments");
        c || sketch.Util.isTouchDevice() || (c = true, "/" !== window.location.pathname ? (n(), t()) : t("horizontal"));
    }

    function t(e) {
        r.length && (r.addClass(e), $.ajax({
            url: "http://sketch-toy.tumblr.com/api/read/json?callback=?",
            dataType: "script",
            context: this,
            success: function () {
                "object" == typeof tumblr_api_read && tumblr_api_read.posts.length && o(tumblr_api_read.posts)
            }
        }));
    }

    function o(e) {
        if (e && r.length) {
            $("<h3>").text(sketch.Locale.string("featured-sketches") + ":").appendTo(r);
            for (var t = "/" === window.location.pathname ? 6 : 4, o = 0, n = Math.min(e.length, t); n > o; o++) {
                var a = e[o];
                $(['<a href="' + a["photo-link-url"] + '">', '<img src="' + a["photo-url-250"] + '">', "</a>"].join("")).appendTo(r);
            }
        }
    }

    function n() {
        s.length && (s.empty().append("<h3>" + sketch.Locale.string("comments") + ":</h3>", '<div class="fb-comments" data-href="' + sketch.Main.getSketchShareURL() + '" data-width="500" data-num-posts="3"></div>'), s.addClass("visible"), FB.XFBML.parse(s.get(0)))
    }

    function a() {
        c && "/" !== window.location.pathname && n();
    }
    
    var i, r, s, c = false;
    
    return {
        initialize: e,
        update: a
    };
}();

sketch.Dropdown = {
    create: function (e) {
        function t() {
            d.addClass("open");
            u.addClass("open");
            $(document).on("mousedown", h);
        }

        function o() {
            d.removeClass("open");
            u.removeClass("open");
            $(document).off("mousedown", h);
        }

        function n(e) {
            f = e;
            d.find(".value").text(e);
            u.find("button").removeClass("selected");
            u.find('button[data-value="' + f + '"]').addClass("selected");
        }

        function a() {
            return f;
        }

        function i(e) {
            e.preventDefault();
        }

        function r(e) {
            e.preventDefault();
        }

        function s(e) {
            e.preventDefault();
            
            var t = $(e.currentTarget);
            
            if(t.length){
            	n(t.attr("data-value"));
            	o();
            	if("function" == typeof this.onChanged){
            		this.onChanged(f);
            	}
            }
        }

        function c() {
            if(u.hasClass("auto-width")){
            	u.width(d.outerWidth() - 1);
            	t();
            };
        }

        function l() {
            o();
        }

        function h(t) {
            for (var n = t.target, a = true; n && n.getAttribute;) {
                if (n && n == e.get(0)) {
                    a = false;
                    break;
                }
                n = n.parentNode;
            }
            a && o();
        }
        
        var d = e.find(".dropdown-title");
        var u = e.find(".dropdown-list");
        var p = u.find("button");
        
        f = null;
        
        e.on("mouseover", $.proxy(c, this));
        e.on("mouseout", $.proxy(l, this));
        d.on("click", $.proxy(i, this));
        d.on("mousedown", $.proxy(r, this));
        p.on("click", $.proxy(s, this));
        
        this.setValue = n;
        this.getValue = a;
    }
};



sketch.Main = function () {
	
    function e(e) {
        $(document.body).addClass("loading");
        sketch.IO.loadSketch(e, function (e, t) {
            $(document.body).removeClass("loading");
            "success" === e ? Z.injectSketch(t) : gt = [];
        });
    }

    function t(e) {
        
    	replayProgressBefore = wt || 0, wt = Math.max(0, Math.min(e, 1));
        
        var t = Math.ceil(wt * mt);
        var o = 0;
        
        At.replayControlsProgress.css("width", 100 * wt + "%");
        
        gt = [];
        
        e: for (var n = 0, a = vt.length; a > n; n++) {
            var i = gt[n] = gt[n] || {
                color: vt[n].color,
                thickness: vt[n].thickness,
                perspective: vt[n].perspective,
                dashed: vt[n].dashed,
                eraser: vt[n].eraser,
                points: []
            };
            St = i.perspective;
            var s = vt[n].points.concat();
            if (t > o + s.length) { 
            	o += s.length, i.points = s;
            } else {
                for (var c = 0, l = s.length; l > c; c++) {
                    var h = s[c];
                    if (i.points.push(h), o++ > t) break e;
                }
        	}
        }
        
        1 === wt && (St = Dt);
    }

    function o() {
        xt = true;
        $("html").addClass("replaying");
        clearInterval(bt);
        bt = setInterval(function () {
            var e = dt;
            mt > 3e4 ? e *= 2 : mt > 15e3 && (e *= 1.5);
            var o = Math.ceil(wt * mt) + e;
            t(o / mt);
        }, ht);
    }

    function n() {
        clearInterval(bt);
    }

    function i() {
        $("html").removeClass("replaying");
        clearInterval(bt);
        
        if(xt){
        	xt = false;
        	wt = 1;
        	gt = vt;
        	Mt = Dt;
        	St = Dt;
        	X.clearRect(0, 0, W.width, W.height);
        	X.save();
        	X.scale(pt.scale, pt.scale);
        	var e = 999;
            var t = gt[gt.length - 1];
            if (t) {
                var o = t.points[t.points.length - 1];
                o && (e = sketch.Util.distanceBetween(It, o.position));
            }
            
            xt && (Mt += .08 * (St - Mt));
            
            Mt = sketch.Util.wrapNumber(Mt + Et, 1);
            Et *= .8;
            (Rt.spaceDown || Rt.leftDown || Rt.rightDown) && (Ut = 1);
            It.down && Rt.spaceDown ? Et += It.diff.x / pt.width : Rt.leftDown && !Rt.rightDown ? Et -= .005 : Rt.rightDown && !Rt.leftDown ? Et += .005 : It.down && Math.abs(e) > lt && (t.points.push({
                position: {
                    x: It.x,
                    y: It.y
                },
                normal: {
                    x: It.x,
                    y: It.y
                }
            }), yt++, zt || f(It.x, It.y, 5, Mt, Tt)), It.diff.x = 0, It.diff.y = 0;
            
            for (var e = gt.length, t = 0; e > t; t++) {
                var o = gt[t],
                    n = o.color || "#000000",
                    a = o.thickness,
                    i = sketch.Util.wrapNumber(2 * (Mt - o.perspective), 2),
                    r = o.dashed,
                    s = o.eraser,
                    c = o.points,
                    l = c.length,
                    h = c[0],
                    d = c[1];
                if (s && (X.save(), X.globalCompositeOperation = "destination-out"), l > 1) {
                    r || X.beginPath();
                    for (var u = 1, p = c.length; p > u; u++) {
                        r && X.beginPath(), 1 > sketch.Util.distanceBetween(h.position, h.normal) && (h.position.x += (Math.random() - .5) * Lt, h.position.y += (Math.random() - .5) * Lt), h.position.x += (h.normal.x - h.position.x) * Ct, h.position.y += (h.normal.y - h.position.y) * Ct;
                        var f = h.position.x,
                            k = d.position.x;
                        f += i * (h.position.x - .5 * tt) * (0 > i ? 1 : -1), k += i * (d.position.x - .5 * tt) * (0 > i ? 1 : -1), (1 == u || r) && X.moveTo(f, h.position.y), X.quadraticCurveTo(f, h.position.y, f + (k - f) / 2, h.position.y + (d.position.y - h.position.y) / 2), h = c[u], d = c[u + 1], r && b(a, n)
                    }
                    r || (b(a, n), X.closePath())
                } else 1 === l && (h.position.x += (Math.random() - .5) * Lt, h.position.y += (Math.random() - .5) * Lt, h.position.x += (h.normal.x - h.position.x) * Ct, h.position.y += (h.normal.y - h.position.y) * Ct, y(h.position.x + i * (h.position.x - .5 * tt) * (0 > i ? 1 : -1), h.position.y, a / 2, n));
                s && X.restore()
            }
            
            for (var u = 0; kt.length > u; u++) {
                var g = kt[u];
                var i = sketch.Util.wrapNumber(2 * (Mt - g.perspective), 2);
                g.position.x += g.velocity.x, g.position.y += g.velocity.y;
                var v = g.position.x;
                v += i * (g.position.x - .5 * pt.width) * (0 > i ? 1 : -1);
                g.alpha *= .94;
                
                var m = {
                    r: 0,
                    g: 0,
                    b: 0
                };
                
                g.color && (m = sketch.Util.hexToRGB(g.color));
                X.fillStyle = "rgba(" + m.r + "," + m.g + "," + m.b + "," + g.alpha + ")";
                X.fillRect(v, g.position.y, 1, 1);
                .05 > g.alpha && (kt.splice(u, 1), u--);
            }
            
            if (Ut > 0) {
                X.save(), X.globalAlpha = Math.max(Ut, 0), X.beginPath(), X.scale(1, .5);
                for (var w = Mt * Math.PI - Math.PI / 2, u = 0; 2 > u; u++) {
                    var x = 0 == u ? ct : 0;
                    X.moveTo(tt / 2, 1.7 * ot + 2);
                    X.arc(tt / 2, 1.7 * ot + x, st, w - .2, w + .2, true);
                    X.closePath();
                    X.lineWidth = 4;
                    X.strokeStyle = "rgb(165,106,70)";
                    X.stroke();
                    X.fillStyle = "rgba(240,150,105,0.85)";
                    X.fill();
                    X.beginPath();
                }
                X.restore();
                Ut -= .05;
            }
            
            if (It.over) {
                var m = sketch.Util.hexToRGB(zt ? "#000000" : colorDropdown.getValue() || rt);
                X.beginPath();
                X.arc(It.x, It.y, (sizeDropdown.getValue() || it) / 2, 0, 2 * Math.PI, true);
                X.closePath();
                X.fillStyle = "rgba(" + m.r + "," + m.g + "," + m.b + ",0.4)";
                X.fill();
            }
            
        	X.restore();
        };
    }

    function l(e) {
        var t = $(".color-dropdown .dropdown-title"),
            o = sketch.Util.hexToRGB(e);
        t.toggleClass("light", o.r + o.g > 500 || o.r + o.b > 500 || o.b + o.g > 500), t.css({
            "background-color": e,
            "box-shadow": "2px 2px 1px rgba(" + o.r + "," + o.g + "," + o.b + ",0.4)"
        });
    }

    function d(e) {
    	Q.find(".stencil, .stencil-controls").remove();
    	$("html").removeClass("has-stencil");
    	
        var t = $('<div class="stencil" style="background-image: url(' + e + ')">').appendTo(Q);
        var o = $('<div class="stencil-controls">').text("Background image: ").appendTo(Q);
        var n = $('<a class="stencil-button toggle" href="#">' + sketch.Locale.string("hide") + "</a>").appendTo(o);
        var a = $('<a class="stencil-button clear" href="#">' + sketch.Locale.string("remove") + "</a>").appendTo(o);
        
        setTimeout(function () {
            t.addClass("visible")
        }, 200), n.on("click", function (e) {
            e.preventDefault();
            t.toggleClass("visible");
            n.text(t.hasClass("visible") ? sketch.Locale.string("hide") : sketch.Locale.string("show"));
        }), a.on("click", function (e) {
            e.preventDefault();
            Q.find(".stencil, .stencil-controls").remove();
            $("html").removeClass("has-stencil");
        }), $("html").addClass("has-stencil")
    }

    /*
     * 마우스 이벤트 저장
     */
    function p(e) {
        It.press.x = It.x;
        It.press.y = It.y;
        e.target == W && (xt && i(), $t = sizeDropdown.getValue() || it, Tt = colorDropdown.getValue() || rt, gt.push({
            color: Tt,
            thickness: $t,
            perspective: Mt,
            dashed: Bt,
            eraser: zt,
            points: []
        }), e.preventDefault(), Ot === false && (Ot = true, sketch.Main.trackEvent("Canvas", "Drew First Line"))
        );
    }

    function f(e, t, o, n, a) {
        for (var i = Math.round(Math.random() * o); i--;) kt.push({
            position: {
                x: e,
                y: t
            },
            velocity: {
                x: .5 * Math.random() - .25,
                y: 3 * Math.random()
            },
            alpha: .98,
            perspective: n,
            color: a || "#000000"
        })
    }

    // 지우개 활성화
    function k() {
        At.eraserToggle.toggleClass("on");
        zt = At.eraserToggle.hasClass("on");
    }

    function g() {
        requestAnimFrame(g);
        X.clearRect(0, 0, W.width, W.height);
        X.save();
        X.scale(pt.scale, pt.scale);
        var e = 999;
        var t = gt[gt.length - 1];
        if (t) {
            var o = t.points[t.points.length - 1];
            o && (e = sketch.Util.distanceBetween(It, o.position))
        }
        xt && (Mt += .08 * (St - Mt)), Mt = sketch.Util.wrapNumber(Mt + Et, 1), Et *= .8, (Rt.spaceDown || Rt.leftDown || Rt.rightDown) && (Ut = 1), It.down && Rt.spaceDown ? Et += It.diff.x / pt.width : Rt.leftDown && !Rt.rightDown ? Et -= .005 : Rt.rightDown && !Rt.leftDown ? Et += .005 : It.down && Math.abs(e) > lt && (t.points.push({
            position: {
                x: It.x,
                y: It.y
            },
            normal: {
                x: It.x,
                y: It.y
            }
        }), yt++, zt || f(It.x, It.y, 5, Mt, Tt)), It.diff.x = 0, It.diff.y = 0;
        
        for (var e = gt.length, t = 0; e > t; t++) {
            var o = gt[t],
                n = o.color || "#000000",
                a = o.thickness,
                i = sketch.Util.wrapNumber(2 * (Mt - o.perspective), 2),
                r = o.dashed,
                s = o.eraser,
                c = o.points,
                l = c.length,
                h = c[0],
                d = c[1];
            if (s && (X.save(), X.globalCompositeOperation = "destination-out"), l > 1) {
                r || X.beginPath();
                for (var u = 1, p = c.length; p > u; u++) {
                    r && X.beginPath(), 1 > sketch.Util.distanceBetween(h.position, h.normal) && (h.position.x += (Math.random() - .5) * Lt, h.position.y += (Math.random() - .5) * Lt), h.position.x += (h.normal.x - h.position.x) * Ct, h.position.y += (h.normal.y - h.position.y) * Ct;
                    var f = h.position.x,
                        k = d.position.x;
                    f += i * (h.position.x - .5 * tt) * (0 > i ? 1 : -1), k += i * (d.position.x - .5 * tt) * (0 > i ? 1 : -1), (1 == u || r) && X.moveTo(f, h.position.y), X.quadraticCurveTo(f, h.position.y, f + (k - f) / 2, h.position.y + (d.position.y - h.position.y) / 2), h = c[u], d = c[u + 1], r && b(a, n)
                }
                r || (b(a, n), X.closePath())
            } else 1 === l && (h.position.x += (Math.random() - .5) * Lt, h.position.y += (Math.random() - .5) * Lt, h.position.x += (h.normal.x - h.position.x) * Ct, h.position.y += (h.normal.y - h.position.y) * Ct, y(h.position.x + i * (h.position.x - .5 * tt) * (0 > i ? 1 : -1), h.position.y, a / 2, n));
            s && X.restore()
        }
        
        for (var u = 0; kt.length > u; u++) {
            var g = kt[u],
                i = sketch.Util.wrapNumber(2 * (Mt - g.perspective), 2);
            g.position.x += g.velocity.x, g.position.y += g.velocity.y;
            var v = g.position.x;
            v += i * (g.position.x - .5 * pt.width) * (0 > i ? 1 : -1), g.alpha *= .94;
            var m = {
                r: 0,
                g: 0,
                b: 0
            };
            g.color && (m = sketch.Util.hexToRGB(g.color)), X.fillStyle = "rgba(" + m.r + "," + m.g + "," + m.b + "," + g.alpha + ")", X.fillRect(v, g.position.y, 1, 1), .05 > g.alpha && (kt.splice(u, 1), u--)
        }
        
        if (Ut > 0) {
            X.save(), X.globalAlpha = Math.max(Ut, 0), X.beginPath(), X.scale(1, .5);
            for (var w = Mt * Math.PI - Math.PI / 2, u = 0; 2 > u; u++) {
                var x = 0 == u ? ct : 0;
                X.moveTo(tt / 2, 1.7 * ot + 2), X.arc(tt / 2, 1.7 * ot + x, st, w - .2, w + .2, true), X.closePath(), X.lineWidth = 4, X.strokeStyle = "rgb(165,106,70)", X.stroke(), X.fillStyle = "rgba(240,150,105,0.85)", X.fill(), X.beginPath()
            }
            X.restore(), Ut -= .05
        }
        
        if (It.over) {
            var m = sketch.Util.hexToRGB(zt ? "#000000" : colorDropdown.getValue() || rt);
            X.beginPath(), X.arc(It.x, It.y, (sizeDropdown.getValue() || it) / 2, 0, 2 * Math.PI, true), X.closePath(), X.fillStyle = "rgba(" + m.r + "," + m.g + "," + m.b + ",0.4)", X.fill()
        }
        
        X.restore();
    }

    function b(e, t) {
        X.lineCap = "round";
        X.lineJoin = "round";
        X.lineWidth = e;
        X.strokeStyle = t;
        X.stroke();
    }

    function y(e, t, o, n) {
        X.beginPath();
        X.arc(e, t, o, 0, 2 * Math.PI, true);
        X.fillStyle = n;
        X.fill();
        X.closePath();
    }

    function x(e) {
        e.preventDefault();
        Z.saveSketch();
        Z.trackEvent("Toolbar", "Save/Share");
    }

    function S(e) {
        e.preventDefault();
        xt && i(), gt.length ? Z.saveSketch() : sketch.ShareOverlay.show(), Z.trackEvent("Toolbar", "Share");
    }

    function D(e) {
        e.preventDefault();
        xt && i(), gt.pop(), Z.trackEvent("Toolbar", "Undo");
    }

    function L(e) {
        (!sketch.IO.hasUnsavedChanges() || confirm(sketch.Locale.string("alert-unsaved-confirmation"))) && (gt.length > 0, mt = 0, wt = 0, vt = [], gt = [], kt = [], sketch.URL.writeID(""), yt = 0, Z.trackEvent("Toolbar", "Reset")), e.preventDefault()
    }

    function C(e) {
        if (!sketch.IO.hasUnsavedChanges() || confirm(sketch.Locale.string("alert-unsaved-confirmation"))) {
            var t = gt.length > 0;
            mt = 0, wt = 0, vt = [], gt = [], kt = [], sketch.URL.writeID(""), yt = 0, Z.trackEvent("Toolbar", "New"), t && (window.location = "/")
        }
        e.preventDefault();
    }

    function T(e) {
        At.dashToggle.toggleClass("on"), Bt = At.dashToggle.hasClass("on"), Z.trackEvent("Toolbar", "Dash", Bt ? 1 : 0), e.preventDefault();
    }

    function M(e) {
        k(), Z.trackEvent("Toolbar", "Eraser", zt ? 1 : 0), e.preventDefault();
    }

    function U(e) {
        var t = true;
        switch (e.keyCode) {
        case 32:
            Rt.spaceDown = true;
            break;
        case 37:
            Rt.leftDown = true;
            break;
        case 39:
            Rt.rightDown = true;
            break;
        case 69:
            k();
            break;
        case 90:
            (e.ctrlKey || e.metaKey) && gt.pop();
            break;
        default:
            t = false
        }
        t && (e.preventDefault(), xt && i());
    }

    function F(e) {
        switch (e.keyCode) {
        case 32:
            Rt.spaceDown = false, e.preventDefault();
            break;
        case 37:
            Rt.leftDown = false, e.preventDefault();
            break;
        case 39:
            Rt.rightDown = false, e.preventDefault();
        }
    }

    function I(e) {
        It.down = true;
        Ft = K.offset();
        Ft.left -= $(window).scrollLeft();
        Ft.top -= $(window).scrollTop();
        It.x = (e.clientX - Ft.left) / pt.scale;
        It.y = (e.clientY - Ft.top) / pt.scale;
        p(e);
    }

    function R(e) {
        if(It.over){
        	Ft = K.offset();
            Ft.left -= $(window).scrollLeft();
            Ft.top -= $(window).scrollTop();
        }
        
        It.prev.x = It.x;
        It.prev.y = It.y;
        It.x = (e.clientX - Ft.left) / pt.scale;
        It.y = (e.clientY - Ft.top) / pt.scale;
        It.diff.x = It.x - It.prev.x;
        It.diff.y = It.y - It.prev.y
    }

    function B(e) {
        It.down = false;
        It.x = (e.clientX - Ft.left) / pt.scale;
        It.y = (e.clientY - Ft.top) / pt.scale;
    }

    function z() {
    	Ft = K.offset();
        Ft.left -= $(window).scrollLeft();
        Ft.top -= $(window).scrollTop();
        It.over = true;
    }

    function O() {
        It.over = false;
    }

    function A(e) {
        1 == e.touches.length && "CANVAS" === e.target.nodeName && (It.down = true, Ft = K.offset(), Ft.left += 10, Ft.top -= $(window).scrollTop() - 10, It.x = (e.touches[0].pageX - Ft.left) / pt.scale, It.y = (e.touches[0].pageY - Ft.top) / pt.scale, p(e), e.preventDefault())
    }

    function P(e) {
        1 == e.touches.length && (e.preventDefault(), It.prev.x = It.x, It.prev.y = It.y, It.x = (e.touches[0].pageX - Ft.left) / pt.scale, It.y = (e.touches[0].pageY - Ft.top) / pt.scale, It.diff.x = It.x - It.prev.x, It.diff.y = It.y - It.prev.y)
    }

    function j() {
        It.down = false;
    }

    function N(e) {
        if (e || (e = window.event), yt > 4) {
            var t = sketch.Locale.string("alert-unsaved-statement");
            return e.cancelBubble = true, e.returnValue = t, e.stopPropagation && (e.stopPropagation(), e.preventDefault()), t;
        }
    }

    function V() {
        setTimeout(function () {
            
        }, 500), setTimeout(function () {
            sketch.Related.initialize();
        }, 500)
    }

    function _() {
        var e = 1250;
        $("html").hasClass("wide-scyscraper") && (e = 1330);
        var t = ut && (sketch.Util.isTouchDevice() || e > window.innerWidth);
        $("html").toggleClass("scyscrapes-below", t), ft.width = Math.max(window.innerWidth, et), ft.height = window.innerHeight, pt.scale = 1, pt.width = tt * pt.scale, pt.height = ot * pt.scale, W.width = pt.width, W.height = pt.height, Q.width(pt.width).height(pt.height), pt.x = K.position().left, pt.y = K.position().top, At.spinner.css({
            top: pt.y + (pt.height / 2 - 16)
        }), At.toolbar.width(pt.width), $(".sketch-canvas-wrapper").css("width", t ? pt.width : "initial"), $(".sketch-footer").css({
            left: pt.x,
            width: pt.width
        })
    }

    function q(e) {
        e.preventDefault();
        var t = e.dataTransfer.files;
        if (t.length) {
            var o = new FileReader;
            o.onloadend = G, o.readAsDataURL(t[0])
        }
    }

    function G(e) {
        e.target.result.match(/^data:image/gi) ? d(e.target.result) : alert("Doesn't seem like that's an image. Please try another file.");
    }

    function H(e) {
        n();
        $(document).on("mousemove", Y).on("mouseup", J);
        Y(e);
    }

    function Y(e) {
        var o = (e.clientX - At.replayControls.offset().left) / At.replayControls.width();
        t(o);
        e.preventDefault();
    }

    function J() {
    	xt = true;
    	$("html").addClass("replaying");
    	clearInterval(bt);
    	
    	bt = setInterval(function () {
            var e = dt;
            mt > 3e4 ? e *= 2 : mt > 15e3 && (e *= 1.5);
            var o = Math.ceil(wt * mt) + e;
            t(o / mt);
        }, ht);
        $(document).off("mousemove", Y).off("mouseup", J);
    }
    
    var W, X, K, Q, Z = {};
    var et = 760;
    var tt = 960;
    var ot = 580;
    var nt = 3;
    var at = .7;
    var it = 3;
    var rt = "#000000";
    var st = 50;
    var ct = 6;
    var lt = 4;
    var ht = 20;
    var dt = 2;
    var ut = !(!$("#left-pillar").length || !$("#right-pillar").length);
    var pt = {x: 0,y: 0,scale: 1,width: tt,height: ot};
    var ft = {width: 0,height: 0};
    var kt = [];
    var gt = [];
    var vt = [];
    var mt = 0;
    var wt = 0;
    var bt = 0;
    var yt = 0;
    var xt = false;
    var St = 0;
    var Dt = 0;
    var Lt = nt;
    var Ct = at;
    var Tt = rt;
    var $t = it;
    var Mt = 0;
    var Et = 0;
    var Ut = 0;
    var Ft = {x: 0,y: 0};
    var It = {x: 0,y: 0,prev: {x: 0,y: 0},diff: {x: 0,y: 0},press: {x: 0,y: 0},down: false,over: false};
    var Rt = {spaceDown: false,leftDown: false,rightDown: false};
    var Bt = false;
    var zt = false;
    var Ot = false;
    var At = {toolbar: null,saveButton: null,resetButton: null,dashToggle: null,vibrationDropdown: null,sizeDropdown: null,facebookConnect: null};
    
    Z.initialize = function () {
    	
    	Q = $(".sketch-canvas-container");
    	K = $(".sketch-canvas");
    	W = K.get(0);
    	At.spinner = $("#spinner");
    	At.toolbar = $(".toolbar");
    	At.saveButton = $(".toolbar .save-button");
    	At.undoButton = $(".toolbar .undo-button");
    	At.newButton = $(".toolbar .new-button");
    	At.resetButton = $(".toolbar .reset-button");
    	At.dashToggle = $(".toolbar .dash-toggle");
    	At.eraserToggle = $(".toolbar .eraser-toggle");
    	At.shareButton = $(".toolbar .share-button");
    	At.tweetButton = $(".toolbar .tweet-button");
    	At.replayControls = $(".replay-controls");
    	At.replayControlsProgress = $(".replay-controls .progress");
    	
    	colorDropdown = new sketch.Dropdown.create($(".color-dropdown")), colorDropdown.setValue(Tt), colorDropdown.onChanged = function (e) {
            l(e), Z.trackEvent("Toolbar", "Color", e)
        }, sizeDropdown = new sketch.Dropdown.create($(".size-dropdown")), sizeDropdown.setValue($t), sizeDropdown.onChanged = function (e) {
            Z.trackEvent("Toolbar", "Size", e)
        }, vibrationDropdown = new sketch.Dropdown.create($(".vibration-dropdown")), vibrationDropdown.setValue(1), vibrationDropdown.onChanged = function (e) {
            Lt = nt * e, Z.trackEvent("Toolbar", "Vibration", e)
        };
        
        if (!navigator.userAgent.match(/ipod|ipad|iphone|android/gi)) {
            var e = false;
            try {
                e = "localStorage" in window && null !== window.localStorage;
            } catch (t) {
                e = false;
            }
        };
        
    	sketch.IO.initialize();
    	sketch.Locale.initialize();
    	
        if (W && W.getContext) {
            X = W.getContext("2d");
            W.addEventListener("mousedown", I, false);
            document.addEventListener("mousemove", R, false);
            document.addEventListener("mouseup", B, false);
            W.addEventListener("touchstart", A, false);
            W.addEventListener("touchmove", P, false);
            
            document.addEventListener("touchend", j, false);
            document.addEventListener("keydown", U, false), document.addEventListener("keyup", F, false), document.addEventListener("dragover", function (e) {
                e.preventDefault()
            }, false), document.addEventListener("dragenter", function (e) {
                e.preventDefault()
            }, false), document.addEventListener("dragexit", function (e) {
                e.preventDefault()
            }, false), document.addEventListener("drop", q, false), At.replayControls.on("mousedown", H), At.saveButton.on("click", x), At.shareButton.on("click", S), At.undoButton.on("click", D), At.newButton.on("click", C), At.resetButton.on("click", L), At.dashToggle.on("click", T), At.eraserToggle.on("click", M), window.addEventListener("resize", _, false), window.addEventListener("beforeunload", N, false), $(window).on("load", V), _(), At.toolbar.css("visibility", "visible"), sketch.Util.isTouchDevice() ? $("html").addClass("touch") : (K.on("mouseover", z), K.on("mouseout", O)), "undefined" != typeof chrome && chrome.app && chrome.app.isInstalled ? $("html").addClass("chrome-app-installed") : navigator.userAgent.match(/chrome/gi) && $("html").addClass("chrome-app-capable"), $("html").addClass("initialized"), g();
            var t = sketch.URL.readID();
            t.length >= 1 && e(t)
        }
        
    };
    
    Z.trackEvent = function (e, t, o, n, a) {
        _gaq.push(["_trackEvent", e, t, o, n, a]);
    };
    
    Z.displayError = function (e) {
        alert(e);
    };
    
    Z.getSketchShareURL = function () {
        return window.location.protocol + "//" + window.location.host + "/" + sketch.URL.readID();
    };
    
    Z.isEmpty = function () {
        return 0 === gt.length;
    };
    
    Z.linesToJSON = function () {
        
    	for (var e = 0; gt.length > e; e++){
        	gt[e] && gt[e].points && 0 != gt[e].points.length || (gt.splice(e, 1), e--);
        } 
        	
        var t = "{";
        t += '"p":' + Mt.toFixed(6) + ",", t += '"a":' + Lt.toFixed(6) + ",", t += '"l":[';
        for (var e = 0; gt.length > e; e++) {
            var o = gt[e].points;
            t += "{", t += '"t":' + gt[e].thickness + ",", t += '"p":' + (0 == gt[e].perspective ? "0.000100" : gt[e].perspective.toFixed(6)) + ",", t += '"d":' + (gt[e].dashed ? 1 : 0) + ",", t += '"e":' + (gt[e].eraser ? 1 : 0) + ",", gt[e].color && "#000000" !== gt[e].color && (t += '"c":"' + gt[e].color + '",'), t += '"points":[';
            for (var n = 0; o.length > n; n++) {
                var a = o[n],
                    i = Math.round(a.normal.x),
                    r = Math.round(a.normal.y);
                t += '"' + i + "x" + r + '"', t += o.length - 1 > n ? "," : "";
            }
            t += "]}", t += gt.length - 1 > e ? "," : "";
        }
        
        return t += "]}";
        
    };
    
    Z.saveSketch = function () {
        gt.length > 0 ? (i(), sketch.IO.saveSketch(), yt = 0) : alert("You need to draw something to save.");
    };
    
    Z.exportSketch = function () {
        Ut = 0, i(), sketch.ShareOverlay.show(), W.style.display = "none";
    };
    
    Z.getSketchAsImage = function () {
        return X.save(), X.globalCompositeOperation = "destination-over", X.fillStyle = "#fff", X.fillRect(0, 0, pt.width, pt.height), X.restore(), W.toDataURL("image/png");
    };
    
    Z.saveSketchAsImage = function () {
        var e = window.open("about:blank", "Your Sketch");
        e.document.write("<img src='" + Z.getSketchAsImage() + "' />");
    };
    
    Z.getSketchAsBlob = function () {
    	
        var e = W.toDataURL("image/png");
        
        if (!e || !window.Blob || !window.atob){
        	return null;
        } 
        
        var t, o = window.atob(e.split(",")[1]),
            n = e.split(",")[0].split(":")[1].split(";")[0],
            a = new ArrayBuffer(o.length),
            i = new Uint8Array(a);
        
        for (t = o.length; t--;) {
        	i[t] = o.charCodeAt(t);
        }
        
        try {
            if (window.DataView) return new Blob([new DataView(a)], {
                type: n
            })
        } catch (r) {}
        
        try {
            return new Blob([i], {
                type: n
            })
        } catch (r) {}
        
        return null;
        
    };
    
    Z.injectSketch = function (e) {
        
    	e.perspective && (Mt = e.perspective, Dt = e.perspective);
        e.amplitude && (Lt = e.amplitude, vibrationDropdown.setValue(Math.round(e.amplitude / nt)));
        vt = e.lines;
        wt = 0;
        mt = 0;
        
        for (var t = 0; vt.length > t; t++) {
            var n = vt[t].points;
            n && (mt += n.length)
        }
        
        xt = true;
        
        $("html").addClass("replaying");
        
        clearInterval(bt);
        
        bt = setInterval(function () {
            var e = dt;
            mt > 3e4 ? e *= 2 : mt > 15e3 && (e *= 1.5);
            var o = Math.ceil(wt * mt) + e;
            t(o / mt);
        }, ht);
    };
    
    //console.log(Z);
    
    return Z;
}();

sketch.Main.initialize();